﻿Public NotInheritable Class KeyboardUtils
    Public Sub New()
        InitializeKeyMap()
    End Sub

    Private Class CharPair
        Public Sub New(normalChar As Char, shiftChar As Nullable(Of Char))
            Me.NormalChar = normalChar
            Me.ShiftChar = shiftChar
        End Sub

        Public NormalChar As Char
        Public ShiftChar As Nullable(Of Char)
    End Class

    Private keyMap As New Dictionary(Of Keys, CharPair)()

    Public Function KeyToString(key As Keys, shiftKeyPressed As Boolean, ByRef character As Char) As Boolean
        Dim result As Boolean = False
        character = " "c
        Dim charPair As CharPair
        If (Keys.A <= key AndAlso key <= Keys.Z) OrElse key = Keys.Space Then
            ' Use as is if it is A～Z, or Space key.
            character = If((shiftKeyPressed), CChar(ChrW(key)), [Char].ToLower(CChar(ChrW(key))))
            result = True
        ElseIf keyMap.TryGetValue(key, charPair) Then
            '
            ' Otherwise, convert by key map.
            If Not shiftKeyPressed Then
                character = charPair.NormalChar
                result = True
            ElseIf charPair.ShiftChar.HasValue Then
                character = charPair.ShiftChar.Value
                result = True
            End If
        End If
        Return result
    End Function


    Private Sub InitializeKeyMap()
        AddKeyMap(Keys.OemTilde, "`~")
        AddKeyMap(Keys.D1, "1!")
        AddKeyMap(Keys.D2, "2@")
        AddKeyMap(Keys.D3, "3#")
        AddKeyMap(Keys.D4, "4$")
        AddKeyMap(Keys.D5, "5%")
        AddKeyMap(Keys.D6, "6^")
        AddKeyMap(Keys.D7, "7&")
        AddKeyMap(Keys.D8, "8*")
        AddKeyMap(Keys.D9, "9(")
        AddKeyMap(Keys.D0, "0)")
        AddKeyMap(Keys.OemMinus, "-_")
        AddKeyMap(Keys.OemPlus, "=+")

        AddKeyMap(Keys.OemOpenBrackets, "[{")
        AddKeyMap(Keys.OemCloseBrackets, "]}")
        AddKeyMap(Keys.OemPipe, "\|")

        AddKeyMap(Keys.OemSemicolon, ";:")
        AddKeyMap(Keys.OemQuotes, "'""")
        AddKeyMap(Keys.OemComma, ",<")
        AddKeyMap(Keys.OemPeriod, ".>")
        AddKeyMap(Keys.OemQuestion, "/?")

        AddKeyMap(Keys.NumPad1, "1")
        AddKeyMap(Keys.NumPad2, "2")
        AddKeyMap(Keys.NumPad3, "3")
        AddKeyMap(Keys.NumPad4, "4")
        AddKeyMap(Keys.NumPad5, "5")
        AddKeyMap(Keys.NumPad6, "6")
        AddKeyMap(Keys.NumPad7, "7")
        AddKeyMap(Keys.NumPad8, "8")
        AddKeyMap(Keys.NumPad9, "9")
        AddKeyMap(Keys.NumPad0, "0")
        AddKeyMap(Keys.Add, "+")
        AddKeyMap(Keys.Divide, "/")
        AddKeyMap(Keys.Multiply, "*")
        AddKeyMap(Keys.Subtract, "-")
        AddKeyMap(Keys.[Decimal], ".")
    End Sub

    Private Sub AddKeyMap(key As Keys, charPair As String)
        Dim char1 As Char = charPair(0)
        Dim char2 As Nullable(Of Char) = Nothing
        If charPair.Length > 1 Then
            char2 = charPair(1)
        End If
        keyMap.Add(key, New CharPair(char1, char2))
    End Sub

End Class